#ifdef _WINDOWS
#include <windows.h>
#endif

#include <stdio.h>
#include <gl/gl.h>
#include <gl/glu.h>
#include <math.h>
#include "CGfxOpenGL.h"

// disable implicit float-double casting
#pragma warning(disable:4305)


extern int PosX;
extern int PosY;
extern int PosZ;
extern int LookX;
extern int LookY;
extern int LookZ;
extern int TransOffset;
extern int Roll;
extern int FOV; 
extern Vertex3F SphereCenter; 
//Wk2
extern float ObjPosX;

float Abs(float a) {
    if (a >= 0) return a;
    else        return -a;
}


// returns the xz length of the vertex for a cone slice
float XZLength(Vertex3F *v) {
	return (float)(sqrt(v->x * v->x + v->z * v->z));
}

float MIN(float a, float b) {
    if (a < b) return a;
    else return b;
}

int MIN(int a, int b) {
    if (a < b) return a;
    else return b;
}
int MAX(int a, int b) {
    if (a > b) return a;
    else return b;
}

float MAX(float a, float b) {
    if (a > b) return a;
    else return b;
}
    
float MIN(float a, float b, float c) {
    return MIN(MIN(a, b), c);
}

float MAX(float a, float b, float c) {
    return MAX(MAX(a, b), c);
}



CGfxOpenGL::CGfxOpenGL()
{
}

CGfxOpenGL::~CGfxOpenGL()
{
}

bool CGfxOpenGL::Init()
{   
    // clear to black background
    //glClearColor(0.0, 0.0, 0.0, 0.0);
    glClearColor(0.0, 0.6, 1.0, 0.0);  //green background
   

    // initialize a rotation angle
    m_angle = 0.0f;

    quadric = gluNewQuadric();

    SphereCenter.x = 3;
    SphereCenter.y = 6;
    SphereCenter.z = 0;

    return true;
}

bool CGfxOpenGL::Shutdown()
{
    if (quadric != NULL) {
        delete quadric;
        quadric = NULL;
    }
  
    return true;
}

void CGfxOpenGL::SetupProjection(int width, int height)
{
    if (height == 0)                    // don't want a divide by zero
    {
        height = 1;                 
    }

    glViewport(0, 0, width, height);        // reset the viewport to new dimensions
    glMatrixMode(GL_PROJECTION);            // set projection matrix current matrix
    glLoadIdentity();                       // reset projection matrix

    // calculate aspect ratio of window
    gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,1.0f,1000.0f);

    glMatrixMode(GL_MODELVIEW);             // set modelview matrix
    glLoadIdentity();                       // reset modelview matrix

    m_windowWidth = width;
    m_windowHeight = height;
}

void CGfxOpenGL::Prepare(float dt)
{
    m_angle += 0.1f;

    //SphereCenter.x = 0;
    //SphereCenter.y = 2;
    //SphereCenter.z = 0;
   
}


void xZFloor(double y) {
	int wdQuads = 10;           // number of quad faces across (in x)
	int htQuads = 10;           // number fo quad faces into or out of the screen (in y)
	double dx = 10.0;           // horiz space between vertices
	double dz = 10.0;           // vert space between vertices
	double x, z;             // x, y, z, for each vertex
	int iz, ix;                 // integer counters in x and y directions
	int wdVertices, htVertices; // wd & ht of grid in vertices
	int quadX, quadZ;           // integer coutners for each quad in x and y directions
	int topLeft, topRight, bottomLeft, bottomRight; // 1-based index for each vertex of the quad
    Vertex3F* terrain;

    // calc number of vertices
	wdVertices = wdQuads + 1;
	htVertices = htQuads + 1;

    terrain = new Vertex3F[wdVertices * htVertices];

    // calc the x, y , z for each vertex
	for (iz=0; iz < htVertices; iz++) {
		for (ix=0; ix < wdVertices; ix++) {
			x = ix * dx;
			z = iz * -dz;

            terrain[iz * wdVertices + ix].x = x;
            terrain[iz * wdVertices + ix].y = y;
            terrain[iz * wdVertices + ix].z = z;
            terrain[iz * wdVertices + ix].r = 1.0;
            terrain[iz * wdVertices + ix].g = 1.0;
            terrain[iz * wdVertices + ix].b = 1.0;
		}
	}


    // calc the vertex indices for each triangle
    // loop through each quad in the grid
	for (quadZ=0; quadZ < htQuads; quadZ++) {
		for (quadX=0; quadX < wdQuads; quadX++) {
            // calc the indexes of the 4 corners of the quad
			topLeft = quadZ * wdVertices + quadX;
            topRight = topLeft + 1;
			bottomLeft = topLeft + wdVertices;
			bottomRight = bottomLeft + 1;

            glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

            glBegin(GL_QUADS);
                glColor3f(terrain[bottomLeft].r, terrain[bottomLeft].g, terrain[bottomLeft].b);
                glVertex3f(terrain[bottomLeft].x, terrain[bottomLeft].y, terrain[bottomLeft].z);

                glColor3f(terrain[bottomRight].r, terrain[bottomRight].g, terrain[bottomRight].b);
                glVertex3f(terrain[bottomRight].x, terrain[bottomRight].y, terrain[bottomRight].z);

                glColor3f(terrain[topRight].r, terrain[topRight].g, terrain[topRight].b);
                glVertex3f(terrain[topRight].x, terrain[topRight].y, terrain[topRight].z);

                glColor3f(terrain[topLeft].r, terrain[topLeft].g, terrain[topLeft].b);
                glVertex3f(terrain[topLeft].x, terrain[topLeft].y, terrain[topLeft].z);

            glEnd();
		}
	}

    delete[] terrain;
}


void CGfxOpenGL::Render()
{
    // enable z or depth buffer testing
    glEnable(GL_DEPTH_TEST);

    // clear screen and depth buffer
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);     

    glMatrixMode(GL_PROJECTION);            // set projection matrix current matrix
    glLoadIdentity();                       // reset projection matrix

    // set up camera perspective projection
    gluPerspective(FOV, float(m_windowWidth) / m_windowHeight, 1.0f, 1000.0f);

    glMatrixMode(GL_MODELVIEW);             // set modelview matrix
    glLoadIdentity();                       // reset modelview matrix

    // set up camera roll and look at point
    glRotatef(Roll, 0.0f, 0.0f, 1.0f);
	gluLookAt(PosX, PosY, PosZ, LookX, LookY, LookZ, 0, 1, 0);

    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    glEnable(GL_DEPTH_TEST);

    // center the floor
    glTranslatef(-50.0, 0.0, 25.0f);

    // call function to draw a floor for perspective
    xZFloor(0);

    // undo the previous floor transform
    glTranslatef(50.0, 0.0, -25.0f);


    // draw some spheres
	glColor3f(1, 0, 0);                 //color blue
	glTranslatef(ObjPosX, 0, 0);
	gluSphere(quadric, 1.0f, 20, 20);  // has radius 1

	
	//glColor3f(1.0, 1.0, 0.0);			//color yellow
	//glTranslatef(15.0, 0.0, 0.0f);
	//gluSphere(quadric, 2.0f, 20, 20);	// has radius


}